package com.jeehentor.utils;

import com.alibaba.fastjson2.JSON;
import com.jeehentor.common.api.vo.LoginUser;
import com.jeehentor.common.vo.Result;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.ParseException;
import java.util.Date;
import java.util.UUID;

/**
 * JWT工具类
 * @author wzd
 */
public class JWTUtil {
    /**
     * 密钥
     */
    private static final String SECRET = "trs1vfde5rsgh9jhjpolm1nb6vcx3zaqwe4rfxc";

    /**
     * 过期时间7天，单位毫秒
     */
    private static final long EXPIRE = 1000 * 60 * 60 * 24 * 7;

    /**
     * 获取盐值
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String getSalt() throws NoSuchAlgorithmException {
        // Use a SecureRandom generator, SHA1PRNG算法是基于SHA-1实现且保密性较强的随机数生成器
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        // Create array for salt
        byte[] salt = new byte[16];
        // Get a random salt
        secureRandom.nextBytes(salt);
        // 将十进制数转换成十六进制(使用&运算，正数部分没变，负数部分二进制从右往左第9位及以上都为0
        StringBuilder builder = new StringBuilder();
        for (byte num : salt) {
            builder.append(Integer.toString((num & 0xff) + 0x100, 16).substring(1));
        }
        return builder.toString();
    }

    /**
     * 创建token
     *
     * @param user 用户信息
     * @return 令牌
     */
    public static String createToken(LoginUser user) {
        try {
            //对密钥进行签名
            JWSSigner jwsSigner = new MACSigner(SECRET);
            long now = System.currentTimeMillis();
            //准备JWS header
            JWSHeader jwsHeader = new JWSHeader
                    .Builder(JWSAlgorithm.HS256)
                    .type(JOSEObjectType.JWT)
                    .build();

            //准备JWS payload
            user.setJti(UUID.randomUUID().toString());
            user.setIat(now);
            user.setExp(now + EXPIRE);


            Payload payload = new Payload(JSON.toJSONString(user));

            //封装JWS对象
            JWSObject jwsObject = new JWSObject(jwsHeader, payload);

            //签名
            jwsObject.sign(jwsSigner);

            return jwsObject.serialize();

        } catch (JOSEException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 验证并获取用户信息
     *
     * @param token 令牌
     * @return 解析后用户信息
     */
    public static Result<LoginUser> verifyToken(String token) {
        JWSObject jwsObject;
        try {
            jwsObject = JWSObject.parse(token);

            //HMAC验证器
            JWSVerifier jwsVerifier = new MACVerifier(SECRET);
            if (!jwsObject.verify(jwsVerifier)) {
                return Result.error("token无效");
            }

            long now = System.currentTimeMillis();
            String payload = jwsObject.getPayload().toString();
            LoginUser user = JSON.parseObject(payload, LoginUser.class);
            if (user.getExp() == null || user.getExp() < now) {
                return Result.error("token已过期");
            }

            return Result.ok(user);
        } catch (ParseException | JOSEException e) {
            e.printStackTrace();
            return Result.error("token解析异常");
        }
    }
    /**
     * 自动刷新token
     * 如果token剩余时间小于指定阈值（例如1天），则重新生成token
     *
     * @param user 当前用户
     * @param thresholdMillis 阈值（毫秒），比如1天：1000*60*60*24
     * @return 新token，如果不用刷新则返回null
     */
    public static String refreshIfNeeded(LoginUser user, long thresholdMillis) {
        long now = System.currentTimeMillis();
        long remaining = user.getExp() - now;
        if (remaining <= thresholdMillis) {
            // 剩余时间小于设定阈值 -> 刷新token
            return createToken(user);
        }
        return null; // 不需要刷新
    }
}
